package com.wei.czz.framework.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wei.czz.common.constant.Constant;
import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.tool.PageQuery;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.common.sms.SmsTemplateFormVo;
import com.wei.czz.framework.common.handler.redis.RedisHashHandler;
import lombok.AllArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.wei.czz.framework.common.dao.SmsTemplateDao;
import com.wei.czz.framework.common.entity.SmsTemplateEntity;
import com.wei.czz.framework.common.service.SmsTemplateService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2024-06-17 21:41:28
 * className: SmsTemplateServiceImpl
 * version: 1.0
 * description:
 */
@Service("smsTemplateService")
@AllArgsConstructor
public class SmsTemplateServiceImpl extends ServiceImpl<SmsTemplateDao, SmsTemplateEntity> implements SmsTemplateService {

    private static final Logger log = LoggerFactory.getLogger(SmsTemplateServiceImpl.class);

    private final RedisHashHandler redisHashHandler;

    private final RedissonClient redissonClient;

    @Override
    public void saveOrEdit(SmsTemplateEntity smsTemplate) {
        Long id = smsTemplate.getId();
        if (Objects.isNull(id)) {
            int count = baseMapper.insert(smsTemplate);
            log.info("插入短信模板完成。count={}", count);
        } else {
            int count = baseMapper.updateById(smsTemplate);
            log.info("修改短信模板完成。count={}", count);
        }
    }

    @Override
    public SmsTemplateEntity find(Integer type) {

        /*
            获取缓存
         */
        String hashKey = RedisConstant.HASH + EntityConstant.SMS_TEMPLATE;
        String cacheKey = type.toString();
        SmsTemplateEntity smsTemplate = redisHashHandler.get(hashKey, cacheKey);
        if (Objects.nonNull(smsTemplate)) {
            log.info("从redis缓存中获取到短信模板。{}", smsTemplate);
            return smsTemplate;
        }

        /*
            加锁
         */
        String lockKey = RedisConstant.LOCK + hashKey + Constant.SPLIT + cacheKey;
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();

        try {
            // double check
            smsTemplate = redisHashHandler.get(hashKey, cacheKey);
            if (Objects.nonNull(smsTemplate)) {
                log.info("double check 从redis缓存中获取到短信模板。{}", smsTemplate);
                return smsTemplate;
            }

            LambdaQueryWrapper<SmsTemplateEntity> smsTemplateLambdaQueryWrapper = new LambdaQueryWrapper<>();
            smsTemplateLambdaQueryWrapper.eq(SmsTemplateEntity::getType, type)
                    .eq(SmsTemplateEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
            // 查询
            List<SmsTemplateEntity> smsTemplateList = baseMapper.selectList(smsTemplateLambdaQueryWrapper);
            log.info("查询短信模板完成。type={} size={}", type, smsTemplateList.size());
            if (smsTemplateList.isEmpty()) {
                // 缓存一个空值
                redisHashHandler.put(hashKey, cacheKey, null);
                return null;
            }
            if (smsTemplateList.size() > 1) {
                log.warn("存在多个同类型短信模板，请检查处理。type={}", type);
                // 存在多个同类型模板，排序取版本号最高的模板
                smsTemplateList.sort(Comparator.comparing(SmsTemplateEntity::getVersion).reversed());
            }
            smsTemplate = smsTemplateList.get(0);
            log.info("短信模板：{}", smsTemplate);

            // 添加缓存
            redisHashHandler.put(hashKey, cacheKey, smsTemplate);

            return smsTemplate;
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    public PageDto<SmsTemplateEntity> getPageList(SmsTemplateFormVo smsTemplateFormVo) {

        // mp分页对象
        Page<SmsTemplateEntity> page = PageQuery.initPage(smsTemplateFormVo);

        LambdaQueryWrapper<SmsTemplateEntity> smsTemplateLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 匹配条件
        smsTemplateLambdaQueryWrapper.eq(Objects.nonNull(smsTemplateFormVo.getCode()), SmsTemplateEntity::getCode,
                        smsTemplateFormVo.getCode())
                .eq(Objects.nonNull(smsTemplateFormVo.getChannel()), SmsTemplateEntity::getChannel,
                        smsTemplateFormVo.getChannel())
                .eq(Objects.nonNull(smsTemplateFormVo.getStatus()), SmsTemplateEntity::getStatus,
                        smsTemplateFormVo.getStatus())
                .eq(SmsTemplateEntity::getDeleteStatus, smsTemplateFormVo.getDeleteStatus());
        // 查询数据
        baseMapper.selectPage(page, smsTemplateLambdaQueryWrapper);
        log.info("分页查询短信模板完成。list.size={} totalNum={}", page.getRecords().size(), page.getTotal());

        return new PageDto<>(page);
    }

    @Override
    public SmsTemplateEntity get(Long id) {
        // 查询
        SmsTemplateEntity smsTemplate = baseMapper.selectById(id);
        if (Objects.isNull(smsTemplate)) {
            log.info("短信模板不存在");
            throw new CzzException(ResultEnum.ILLEGAL_FAIL);
        }
        if (CommonEnum.ONE.getValue().equals(smsTemplate.getDeleteStatus())) {
            log.info("短信模板已删除");
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "短信模板已删除，请确认");
        }
        return smsTemplate;
    }

    @Override
    public List<SmsTemplateEntity> getList(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            log.info("获取短信模板操作，传入的主键列表参数为空");
            return Collections.emptyList();
        }
        LambdaQueryWrapper<SmsTemplateEntity> smsTemplateLambdaQueryWrapper = new LambdaQueryWrapper<>();
        smsTemplateLambdaQueryWrapper.in(SmsTemplateEntity::getId, idList)
                .eq(SmsTemplateEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<SmsTemplateEntity> smsTemplateList = baseMapper.selectList(smsTemplateLambdaQueryWrapper);
        log.info("查询短信模板完成。idList.size={} size={}", idList.size(), smsTemplateList.size());
        return smsTemplateList;
    }

    @Override
    public int optimisticUpdate(SmsTemplateEntity smsTemplate) {
        int count = baseMapper.optimisticUpdate(smsTemplate);
        log.info("乐观锁更新短信模板完成。count={}", count);
        return count;
    }

    @Transactional
    @Override
    public void batchUpdate(List<SmsTemplateEntity> smsTemplateList) {
        if (CollectionUtils.isEmpty(smsTemplateList)) {
            log.info("批量更新短信模板，传入短信模板对象列表参数为空");
            return;
        }
        boolean bool = this.updateBatchById(smsTemplateList);
        log.info("批量更新短信模板完成。bool={}", bool);
    }

    @Override
    public void delete(List<Long> idList) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<SmsTemplateEntity> smsTemplateLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        smsTemplateLambdaUpdateWrapper.set(SmsTemplateEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(SmsTemplateEntity::getUpdateTime, date)
                .set(SmsTemplateEntity::getUpdateUser, userPo.getUsername())
                .set(SmsTemplateEntity::getUpdateUserId, userPo.getUserId());
        smsTemplateLambdaUpdateWrapper.in(SmsTemplateEntity::getId, idList)
                .eq(SmsTemplateEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 删除
        int count = baseMapper.update(smsTemplateLambdaUpdateWrapper);
        log.info("删除短信模板完成。count={}", count);
    }
}
